/**
 * @file: bitset.cpp 
 * Easy example of c++ code
 */
/**
 * Copyright 2011 MIPT-COMPILER team
 */

#include "bitset.hpp"


OutOfRangeException::OutOfRangeException( unsigned ireal, unsigned imax)
{
    real = ireal;
    max = imax;
};

std::string  OutOfRangeException::data()
{
    std::stringstream ss;
    ss << "ERROR: No " << real << " element in bitset! Max is " << max - 1 << "!\n";
    return ss.str();
};


std::ostream& operator << (std::ostream &cout_, BitSet &obj)
{
    cout_ << obj.serialize();
    return cout_;
};

BitSet::BitSet( unsigned inp_num_of_bits)
{
    num_of_bits = inp_num_of_bits;
    unsigned array_len = ( num_of_bits % 8) ? 1: 0;
    array_len += num_of_bits / 8;
    first_byte = new char [array_len];
};

BitSet::~BitSet()
{
    delete [] first_byte;
    first_byte = 0;
    num_of_bits = 0;        
};

char BitSet::getBit( unsigned bit_num)
{
    if ( bit_num >= num_of_bits )
        throw  OutOfRangeException( bit_num, num_of_bits);
 
    unsigned byte_to_use = bit_num / 8;
    char mask = 1;
    bit_num = bit_num % 8;
    mask = mask << ( 7 - bit_num); 

    if ( mask & first_byte [byte_to_use] ) return 1;
    else return 0;
};
    
void BitSet::setBit( unsigned bit_num, bool bit_value)
{
    if ( bit_num >= num_of_bits )
        throw OutOfRangeException( bit_num, num_of_bits);

    unsigned byte_to_use = bit_num / 8, byte_value = bit_value;
    char mask = 1;
    bit_num = bit_num % 8;
    byte_value = byte_value << ( 7 - bit_num);
        
    mask = mask << ( 7 - bit_num);
    mask = ~mask;

    if ( bit_value )
        first_byte [byte_to_use] = 
        first_byte [byte_to_use] | byte_value;     
    else    
        first_byte [byte_to_use] = 
        first_byte [byte_to_use] & mask;
};    

const std::string BitSet::serialize ()
{
    std::string str;
    str.clear();
    for ( unsigned i = 0; i < num_of_bits; i++ )
        if ( getBit( i) ) str += "1";
        else str += "0"; 
    return str;
}

